package com.soulless.lazy;

/**
 * 懒汉式单例-双重检查锁
 *
 * <p>
 * 优点：
 * 性能高了，线程安全了。
 * 缺点：
 * 可读性难度加大，不够优雅。
 * </p>
 *
 * @author zenglei
 * @date 2022/11/16 14:50
 */
public class LazyDoubleCheckSingleton {

    private volatile static LazyDoubleCheckSingleton instance;

    private LazyDoubleCheckSingleton() {}

    /**
     * synchronized 保证线程安全，控制资源永远只有一个线程占用
     * @return
     */
    public static LazyDoubleCheckSingleton getInstance() {
        /**
         * 检查是否要阻塞，这样判断不用每一次都去竞争锁。
         */
        if (null == instance) {
            synchronized (LazyDoubleCheckSingleton.class) {
                /**
                 * 检查是否要重新创建实例，如果不检验，当第一个线程释放锁，第二个线程获得锁时，会重复创建
                 */
                if (null == instance) {
                    instance = new LazyDoubleCheckSingleton();
                    /**
                     * 存在指令重排序的问题，所以要加【volatile】关键字（禁止指令重排）
                     */
                }
            }
        }

        return instance;
    }

    //region 测试模块
    static class LazyDoubleCheckSingletonThread implements Runnable {
        @Override
        public void run() {
            LazyDoubleCheckSingleton ins = LazyDoubleCheckSingleton.getInstance();
            System.out.println(Thread.currentThread().getName() + " : " + ins);
        }
    }

    static class MultiThreadTest {
        public static void main(String[] args) {
            Thread t1 = new Thread(new LazyDoubleCheckSingletonThread());
            Thread t2 = new Thread(new LazyDoubleCheckSingletonThread());
            t1.start();
            t2.start();
            System.out.println("End");
        }
    }
    //endregion

}
